package com.ebspp.server.resource;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import com.ebspp.thrift.Identity;
import com.ebspp.thrift.ResourceType;

/**
 * Global resource manager of the EBS++ server
 * @author x23pan
 *
 */
public class ResourceManager 
{
	//private static Map<ResourceType, Integer> MAX_RESOURCE =
			//new HashMap<ResourceType, Integer>();
	
	static Map<ResourceType, Integer> resourceMap = 
			Collections.synchronizedMap(new HashMap<ResourceType, Integer>());
	
	static Map<Identity, ClientResManager> clientResMap =
			Collections.synchronizedMap(new HashMap<Identity, ClientResManager>());
	
	static 
	{
		resourceMap.put(ResourceType.CPU, 100);
		resourceMap.put(ResourceType.STORAGE, 1024);
		resourceMap.put(ResourceType.TXN_STORAGE, 1024);
		resourceMap.put(ResourceType.NETWORK, 1024);
		resourceMap.put(ResourceType.MEMORY, 1024);
	}
	
	synchronized public static boolean updateResource(Map<ResourceType, Integer> updates, Identity id)
	{
		//check if the resource pool has enough resource for the request
		for(ResourceType type : updates.keySet())
		{
			int diff = updates.get(type);
			int val = resourceMap.get(type);
			if(val - diff < 0)
				return false;
		}
		
		
		ClientResManager cliResManager = clientResMap.get(id);
		if(cliResManager == null)
			cliResManager = createClientResManager(id);
		//check if the client is releasing more resource than it has
		if(!cliResManager.canAlloc(updates))
			return false;

		
		//update the global resource map and the user local resource map
		for(ResourceType type : updates.keySet())
			resourceMap.put(type, resourceMap.get(type) - updates.get(type));
		cliResManager.alloc(updates);
		return true;
	}
	
	public static ClientResManager getResManager(Identity id)
	{
		return clientResMap.get(id);
	}
	
	public synchronized static ClientResManager createClientResManager(Identity id)
	{
		ClientResManager cliResManager = clientResMap.get(id);
		if(cliResManager != null)
			return cliResManager;
		
		cliResManager = new ClientResManager(id);
		clientResMap.put(id, cliResManager);
		return cliResManager;
	}
	
	
	public static int getResource(ResourceType type)
	{
		return resourceMap.get(type);
	}

}



